package com.heima.behavior.service.impl;

import com.heima.behavior.pojo.ApFollowBehavior;
import com.heima.behavior.pojo.ApLikesBehavior;
import com.heima.behavior.pojo.ApReadBehavior;
import com.heima.behavior.service.BehaviorService;
import com.heima.model.behavior.dto.ArticleBehaviorDto;
import com.heima.model.behavior.dto.FollowBehaviorDto;
import com.heima.model.behavior.dto.LikesbehaviorDto;
import com.heima.model.behavior.dto.ReadBehaviorDto;
import com.heima.model.behavior.vo.ArticleBehaviorVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.utils.common.WmThreadLocalUtil;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;

@Service
public class BehaviorServiceImpl implements BehaviorService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    //关注
    @Override
    public ResponseResult follow_behavior(FollowBehaviorDto dto) {
        //校验参数
        if (StringUtils.isEmpty(dto.getAuthorId()) || StringUtils.isEmpty(dto.getArticleId())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }//Operation=0 关注   Operation=1取消关注
        //定义2个hashkey   key
        String follow_hashKey = "follow_" + WmThreadLocalUtil.get();
        String follow_key = dto.getAuthorId() + "";
        String seguito_hashKey = "seguito_" + dto.getAuthorId();
        String seguito_key = WmThreadLocalUtil.get() + "";
        //0.将数据保存到redis
        //关注表 hashKey=follow+用户id   key=作者id    value="1"(任意值)
        //受关注表 hashKey=seguito+作者id   key=用户id    value="1"(任意值)

        //1.用户请求的是关注
        //1.1判断用户是否已经互相关注
        Boolean aBoolean = redisTemplate.opsForHash().hasKey(follow_hashKey, follow_key);
        if (dto.getOperation() == 0) {
            //1.2查找redis缓存用户以前是否关注过这个作者
            if (!aBoolean) {//1.3用户未关注这个作者,把数据添加到redis中,  已关注不变
                redisTemplate.opsForHash().put(follow_hashKey, follow_key, "1");
                redisTemplate.opsForHash().put(seguito_hashKey, seguito_key, "1");
                //将数据保存到mongodb中
                ApFollowBehavior apFollowBehavior = new ApFollowBehavior();
                apFollowBehavior.setUserId(WmThreadLocalUtil.get());
                apFollowBehavior.setArticleId(dto.getArticleId());
                apFollowBehavior.setFollowId(dto.getAuthorId());
                apFollowBehavior.setCreatedTime(new Date());
                mongoTemplate.insert(apFollowBehavior);
            }
        }
        //2.用户请求的是取消关注
        if (dto.getOperation() == 1) {
            //1.2查找redis缓存用户以前是否关注过这个作者
            if (aBoolean) {//1.3用户未关注这个作者,把数据添加到redis中,  已关注不变
                redisTemplate.opsForHash().delete(follow_hashKey, follow_key);
                redisTemplate.opsForHash().delete(seguito_hashKey, seguito_key);
                //将mongodb中的数据删除
                Query query = Query.query(Criteria.where("userId").is(WmThreadLocalUtil.get())
                        .and("articleId").is(dto.getArticleId())
                        .and("followId").is(dto.getArticleId()));
                mongoTemplate.remove(query, ApFollowBehavior.class);
            }
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    //点赞
    @Override
    public ResponseResult like(LikesbehaviorDto dto) {
        //1.校验参数
        if (StringUtils.isEmpty(dto.getOperation()) || StringUtils.isEmpty(dto.getArticleId())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //判断用户是点赞还是取消点赞
        //操作方式  点赞:0  取消点赞:1
        //判断用户在redis中有没有存储数据
        Long userId = WmThreadLocalUtil.get();
        //判断用户是否登录,未登录返回
        if (userId == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String like_key = "Like_Key_" + userId;
        //用户在redis缓存是否有历史数据
        Boolean is_bBoolean = redisTemplate.opsForSet().isMember(like_key, dto.getArticleId() + "");
        //redis没有记录:用户执行的点赞操作  而且redis状态为未点赞状态
        if (!is_bBoolean && dto.getOperation() == 0) {
            redisTemplate.opsForSet().add(like_key, dto.getArticleId() + "");
            ApLikesBehavior apLikesBehavior = new ApLikesBehavior();
            apLikesBehavior.setArticleId(dto.getArticleId());
            apLikesBehavior.setType(dto.getType());
            apLikesBehavior.setUserId(userId);
            apLikesBehavior.setCreatedTime(new Date());
            mongoTemplate.save(apLikesBehavior);
        }
        //redis有记录:用户执行的取消点赞操作  而且redis状态为点赞状态
        if (is_bBoolean && dto.getOperation() == 1) {
            redisTemplate.opsForSet().remove(like_key, dto.getArticleId() + "");
            Query query = Query.query(Criteria.where("userId").is(userId).and("articleId").is(dto.getArticleId()));
            mongoTemplate.remove(query, ApLikesBehavior.class);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    //阅读
    @Override
    public ResponseResult readBehavior(ReadBehaviorDto dto) {
        //1/校验参数
        if (StringUtils.isEmpty(dto.getArticleId()) || StringUtils.isEmpty(dto.getCount())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2.判断用户有没有登录或者有手机型号
        Long userId = WmThreadLocalUtil.get();
        if (userId == null && dto.getEquipmentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //查询mongodb数据库,
        Criteria criteria = new Criteria();
        criteria.orOperator(Criteria.where("userId").is(userId), Criteria.where("equipmentId").is(dto.getEquipmentId()))
                .andOperator(Criteria.where("articleId").is(dto.getArticleId()));
        Query query = new Query(criteria);
        ApReadBehavior apReadBehavior = mongoTemplate.findOne(query, ApReadBehavior.class);
        // 有数据:更新数据,
        if (apReadBehavior != null) {
            apReadBehavior.setUpdatedTime(new Date());
            apReadBehavior.setCount(apReadBehavior.getCount() + 1);
            apReadBehavior.setPercentage(dto.getPercentage());
            apReadBehavior.setLoadDuration(dto.getLoadDuration());
            apReadBehavior.setCreatedTime(new Date());
            mongoTemplate.save(apReadBehavior);
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        // 没有数据:添加数据
        apReadBehavior = new ApReadBehavior();
        apReadBehavior.setUserId(userId);
        apReadBehavior.setEquipmentId(dto.getEquipmentId());
        apReadBehavior.setArticleId(dto.getArticleId());
        apReadBehavior.setCount(1);
        apReadBehavior.setReadDuration(dto.getReadDuration());
        apReadBehavior.setPercentage(dto.getPercentage());
        apReadBehavior.setLoadDuration(dto.getLoadDuration());
        apReadBehavior.setCreatedTime(new Date());
        apReadBehavior.setUpdatedTime(new Date());
        mongoTemplate.save(apReadBehavior);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    //展示
    @Override
    public ResponseResult loadArticle(ArticleBehaviorDto dto) {
        if (dto.getArticleId() == null || dto.getAuthorId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //封装数据
        ArticleBehaviorVo articleBehaviorVo = new ArticleBehaviorVo();
        //todo
        //不喜欢和收藏未完成
        articleBehaviorVo.setIsunlike(false);
        articleBehaviorVo.setIscollection(false);
        //关注
        Boolean follow_key = redisTemplate.opsForHash().hasKey("follow_" + WmThreadLocalUtil.get(), dto.getAuthorId() + "");
        articleBehaviorVo.setIsfollow(follow_key);
        //点赞
        Boolean like_key = redisTemplate.opsForSet().isMember("Like_Key_" + WmThreadLocalUtil.get(), dto.getArticleId() + "");
        articleBehaviorVo.setIslike(like_key);
        return ResponseResult.okResult(articleBehaviorVo);
    }
}
